React(19) - ErrorBoundary


Posted by TempuraEngineer on 2024-04-12

目錄


ErrorBoundary是甚麼


以React撰寫的網頁在渲染時出錯的話(就像上圖的throw Error),React會把整個UI畫面都移除掉,為了避免這個慘況就需要使用ErrorBoundary

它會包裹住部分組件,讓被包裹的組件在渲染出錯時不顯示error message,而改成顯示fallback UI的組件

另外需要注意ErrorBoundary只能用class component的形式撰寫

且需要在getDerivedStateFromError 這個生命週期更新state才能成功渲染fallback UI,反之如果只是要再捕捉到錯誤後做某些事的話只要用componentDidCatch即可


奇怪的chunk error

之前遇到了一個奇怪的狀況是每當網頁剛deploy到各個環境上就有機會會在某幾個頁面出現chunk error(客戶端試圖request chunk file卻找不到),但重新整理後又正常了,且恢復正常後到下次deploy前都不會再跳出chunk error

chunk error指的是載入chunk的找不到chunk,看解法前先來瞭解一下甚麼是chunk、code splitting


chunk & code splitting是甚麼

以前端框架撰寫網頁的時候,會需要bundlers (ex:webpack, gulp, grunt, vite) 幫我們打包網站,而code splitting就是其中一件bundler會處理的事

code splitting指的是將程式碼分割成多個小小的 chunk,需要時(進到對應的頁面時)才去下載,藉此提升網站的 initial load performance

隨著你的網站越來越複雜,CSS 和 JS 檔案的大小也會越來越大為了避免一次下載所有檔案,導致網頁載入速度過慢,所以才需要code splitting

Webpack會幫你把chunk file的檔名取成contenthash的形式,每當頁面(或是asset)的內容變動contenthash也會變

在上一段提到chunk error通常出現在發完新版本的時候,而新版本內一定會有內容的變動,加上瀏覽器會試著從快取找資源(舊的chunk),所以才會出錯


現況 & 沒用的方法

接著回到chunk error

在next.js的PR區有人嘗試修正next.js不能設定headers這個問題了,只是直到目前(2024年4月)都沒有人review,所以PR遲遲沒被merge

fix: allow next.config.js overwrite cache-control header

在PR被merge前,只好試試其他方法了😢

以下先列出幾個曾經試過的沒用方法

沒用的方法

  • next.config.js加Cache-Control headers

    你可能會查到有人說可以透過在next.config.js加上Cache-Control headers解決,不過我實際試過並沒有效果

    You cannot set Cache-Control headers in next.config.js for pages or assets, as these headers will be overwritten in production to ensure that responses and static assets are cached effectively.

    官方文件有說「為了確保靜態資源(static asset)被有效率地快取住,所以在production環境下next.config.js內的設定會被覆蓋掉」,也就是說即便設定了Cache-Control headers仍會失效


用ErrorBoundary繞過去

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidCatch(error, errorInfo) {
    if(error.name === 'ChunkError') {
      // 如果捕捉到chunk error就重整
      window.location.reload();
    }
  }

  render() {
    return this.props.children; 
  }
}
<ErrorBoundary>
   // 這裡放會出chunk error的組件 (ex: 頁面組件)
   <Outlet />
</ErrorBoundary>


參考資料

Catching rendering errors with an error boundary
Complete Guide on React Error Boundary

Dynamic Import, Code Splitting, Lazy Loading, and Error Boundaries
React | 為太龐大的程式碼做 Lazy Loading 和 Code Splitting
鐵人賽 Day05 - React 中的 Code splitting(代碼分離)方法
Unveiling the Power of Code-Splitting with Webpack for React and Redux Applications

Cache-Control headers set in next.config.js are overwritten
How to fix ChunkLoadError in your ReactJS application










Related Posts

JS30 Day 21 筆記

JS30 Day 21 筆記

使用 Python 進行中斷點 step by step debug 除錯

使用 Python 進行中斷點 step by step debug 除錯

[ week 1 ] 教教蔡哥學 Git

[ week 1 ] 教教蔡哥學 Git


Comments